import numpy as np

from interpolation import vandermonde_interpolation, lagrange_interpolate, newton_interpolate, piecewise_linear_interpolation, cubic_hermite_interpolate
from utils import uniform_samples, chebyshev_nodes, calculate_average_error, plot_interpolation_comparison

# 标准函数
def sincos_function(x, a=1, b=1, c=1, d=1):
    x = np.array(x)
    return a * np.sin(b * x) + c * np.cos(d * x)

def rational_function(x):
    x = np.array(x)
    return 1 / (x ** 2 + 1)

# 标准函数的导数
def sincos_function_derivative(x, a=1, b=1, c=1, d=1):
    x = np.array(x)
    return a * b * np.cos(b * x) - c * d * np.sin(d * x)

def rational_function_derivative(x):
    x = np.array(x)
    return -2 * x / ((x ** 2 + 1) ** 2)

#################### 可调节参数 ############################

# 设置插值区间
interval = [-10, 10]
# 设置样本点数量
num_samples = 50
# 设置实验点数量
num_experiments = 1000

# 设置标准函数参数
a, b, c, d = 1, 2, 3, 4

sampling_method_list = ["uniform", "chebyshev"]
# 设置采样方式
sampling_method = sampling_method_list[0]  # 可选: "uniform" or "chebyshev"

function_type_list = ["sincos", "rational"]
# 选择使用的标准函数
function_type = function_type_list[0]  # 可选: "sincos" or "rational"

################### end #############################################

# 选择使用的函数和导数
if function_type == "sincos":
    custom_function = lambda x: sincos_function(x, a, b, c, d)
    custom_function_derivative = lambda x: sincos_function_derivative(x, a, b, c, d)
elif function_type == "rational":
    custom_function = rational_function
    custom_function_derivative = rational_function_derivative
else:
    raise ValueError("Invalid function type.")

# 生成样本点
if sampling_method == "uniform":
    x_samples = uniform_samples(interval[0], interval[1], num=num_samples)
elif sampling_method == "chebyshev":
    x_samples = chebyshev_nodes(interval[0], interval[1], num=num_samples)
else:
    raise ValueError("Invalid sampling method.")

y_samples = custom_function(x_samples)

dy_samples = custom_function_derivative(x_samples)

# 生成实验点
x_experiment = uniform_samples(interval[0], interval[1], num=num_experiments)

# 计算标准函数在实验点的真实值
y_true = custom_function(x_experiment)

# 打印实验设置
print(f"Experiment Setup:")
print(f"Sampling Method: {sampling_method.capitalize()}")
print(f"Interval: {interval}")
print(f"Number of Samples: {num_samples}")
print(f"Number of Experiments: {num_experiments}")
print(f"Standard Function Parameters (a, b, c, d): ({a}, {b}, {c}, {d})")

print("Starting interpolation...")

interpolation_results = {
        # "Vandermonde": vandermonde_interpolation(x_samples, y_samples, x_experiment),
        # "Lagrange": lagrange_interpolate(x_samples, y_samples, x_experiment),
        # "Newton": newton_interpolate(x_samples, y_samples, x_experiment),
        "Piecewise Linear": piecewise_linear_interpolation(x_samples, y_samples, x_experiment),
        "Cubic Hermite": cubic_hermite_interpolate(x_samples, y_samples, dy_samples, x_experiment),
    }

errors = {}
for method, y_interp in interpolation_results.items():
    average_error = calculate_average_error(y_true, y_interp)
    errors[method] = average_error

# 输出每种插值方法的平均误差
print("Average Errors:")
for method, error in errors.items():
    print(f"{method}: {error}")

# 作图
plot_interpolation_comparison(x_experiment, y_true, interpolation_results, x_samples, y_samples)